﻿// Author:  Marco van Wieren <mailto:mvwieren@gmail.com>
// Year:    2012
// License: Microsoft Public License (Ms-PL)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Taxonomy;
using Microsoft.SharePoint.WebControls;
using System.Web.UI.WebControls;
using System.Web.UI;
using Microsoft.SharePoint.Utilities;
using System.Web;

namespace Mvw.SharePoint.Taxonomy.AutoTagging
{
    /// <summary>
    /// Code behind for ManageInheritedColumns.aspx
    /// </summary>
    public partial class ManageInheritedColumns : LayoutsPageBase
    {
        public string PagePermissionFlagString;
        protected CheckBox ReenableInheritance;
        protected CheckBox UpdateListItems;
        protected Panel TaxonomyPanel;
        protected Button RunButton;

        protected override void OnInit(EventArgs e)
        {
            SPBasePermissions pagePermissionFlag = (SPBasePermissions)Enum.Parse(typeof(SPBasePermissions), PagePermissionFlagString.Replace("SPBasePermissions.", ""));
            // You can change the current setting by changing the following line in ManageWorkspaceTermInfo.aspx: <%@Page PagePermissionFlagString="SPBasePermissions.ManageWeb"%>
            SPWeb web = SPContext.Current.Web;
            if (!web.DoesUserHavePermissions(pagePermissionFlag))
            {
                // build the access denied page
                SPUtility.Redirect(SPUtility.AccessDeniedPage + "?Source=" + SPHttpUtility.UrlKeyValueEncode(web.Site.MakeFullUrl(Request.RawUrl)),
                                   SPRedirectFlags.RelativeToLayoutsPage,
                                   HttpContext.Current);
            }
            base.OnInit(e);
        }

        /// <summary>
        /// In the page onload a number of TaxonomyWebTaggingControls is created that correspond to the number
        /// of WorkspaceTermInfo objects that were found in the WorkspaceTermInfoList that is stored in the current 
        /// web's property bag.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            try
            {
                SPContext.Current.Web.AllowUnsafeUpdates = true;
                HandleOnLoad();
            }
            catch (Exception ex)
            {
                this.ShowMessage(SPUtility.GetLocalizedString("$Resources:GLOBAL_ErrorMsgType", "SPM.Resources",
                    SPContext.Current.Web.Language), ex.Message, "red");
            }
            finally
            {
                SPContext.Current.Web.AllowUnsafeUpdates = false;
            }
        }

        /// <summary>
        /// This method reads the information from each of the TaxonomyWebTaggingControl (there should be one for WorkspaceTermInfo
        /// object stored in the current's web property bag), updates the WorkspaceTermInfoList (the collection of WorkspaceTermInfo
        /// objects), updates the web's property bag to then update the current web, its lists and all webs below it.
        /// Page will be reloaded as the button is set to submit mode.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void RunButtonClick(object sender, EventArgs e)
        {
            try
            {
                SPContext.Current.Web.AllowUnsafeUpdates = true;
                HandleRunButtonClick();
            }
            catch (Exception ex)
            {
                this.ShowMessage(SPUtility.GetLocalizedString("$Resources:GLOBAL_ErrorMsgType", "SPM.Resources",
                    SPContext.Current.Web.Language), ex.Message, "red");
            }
            finally
            {
                SPContext.Current.Web.AllowUnsafeUpdates = false;
            }
        }

        private void HandleOnLoad()
        {
            // Since the TaxonomyWebTaggingControls are created dynamically they need to be recreated also upon PostBack
            if (SPContext.Current.Web.AllProperties["WorkspaceTermInfo"] == null)
            {
                throw new WorkspaceTermInfoNotFoundException(SPUtility.GetLocalizedString("$Resources:GLOBAL_ErrorWorkspaceTermInfoNotFound",
                    "SPM.Resources", SPContext.Current.Web.Language));
            }

            var workspaceTermInfoList = new WorkspaceTermInfoList(SPContext.Current.Web.AllProperties["WorkspaceTermInfo"].ToString());
            if (!workspaceTermInfoList.IsValid)
            {
                throw new ConfigurationDataInvalidException(SPUtility.GetLocalizedString("$Resources:GLOBAL_ErrorConfigurationDataInvalid",
                    "SPM.Resources", SPContext.Current.Web.Language));
            }

            var session = new TaxonomySession(SPContext.Current.Site);
            if (session.TermStores.Count <= 0)
            {
                throw new UnexpectedError(SPUtility.GetLocalizedString("$Resources:GLOBAL_ErrorUnexpected",
                    "SPM.Resources", SPContext.Current.Web.Language));
            }

            foreach (var workspaceTermInfo in workspaceTermInfoList)
            {
                if (!workspaceTermInfo.IsValid)
                {
                    throw new ConfigurationDataInvalidException(SPUtility.GetLocalizedString("$Resources:GLOBAL_ErrorConfigurationDataInvalid",
                        "SPM.Resources", SPContext.Current.Web.Language));
                }

                var taxonomyWebTaggingControl = new TaxonomyWebTaggingControl();

                var termStore = session.TermStores[workspaceTermInfo.TermStoreName];
                if (termStore == null)
                {
                    throw new ConfigurationDataInvalidException(SPUtility.GetLocalizedString("$Resources:GLOBAL_ErrorConfigurationDataInvalid",
                        "SPM.Resources", SPContext.Current.Web.Language));
                }

                var termSet = termStore.GetTermSet(new Guid(workspaceTermInfo.TermSetId));
                if (termSet == null)
                {
                    throw new ConfigurationDataInvalidException(SPUtility.GetLocalizedString("$Resources:GLOBAL_ErrorConfigurationDataInvalid",
                        "SPM.Resources", SPContext.Current.Web.Language));
                }

                taxonomyWebTaggingControl.SspId.Add(termStore.Id);
                taxonomyWebTaggingControl.TermSetId.Add(termSet.Id);
                taxonomyWebTaggingControl.AllowFillIn = true;
                taxonomyWebTaggingControl.IsMulti = workspaceTermInfo.AllowMultipleValues;
                taxonomyWebTaggingControl.ID = "TWTC" + workspaceTermInfo.TaxFieldStaticName;

                if (taxonomyWebTaggingControl.IsMulti)
                {
                    var termLabelGuidPairs = new List<string>();
                    foreach (var termGuid in workspaceTermInfo.TermIds)
                    {
                        termLabelGuidPairs.Add(Ext.TermLabelGuidPair(termSet, termGuid));
                    }
                    taxonomyWebTaggingControl.Text = string.Join(TaxonomyField.TaxonomyMultipleTermDelimiter.ToString(), termLabelGuidPairs.ToArray());

                }
                else
                {
                    if (workspaceTermInfo.TermIds.Count >= 0)
                    {
                        taxonomyWebTaggingControl.Text = Ext.TermLabelGuidPair(termSet, workspaceTermInfo.TermIds[0]);
                    }
                }

                TaxonomyPanel.Controls.Add(taxonomyWebTaggingControl);
                TaxonomyPanel.Controls.Add(new LiteralControl("<br/><br/>"));
            }

            // Now set the correct value for the ReenableInheritance CheckBox
            if (!IsPostBack && SPContext.Current.Web.AllProperties["WorkspaceTermInfoInherit"] != null)
            {
                try
                {
                    ReenableInheritance.Checked = bool.Parse(SPContext.Current.Web.AllProperties["WorkspaceTermInfoInherit"].ToString());
                }
                catch { }
            }
        }

        private void HandleRunButtonClick()
        {
            // TODO Not sure whether the new terms need to be registered with the site (even though this seems to work)
            using (var web = SPContext.Current.Site.OpenWeb(SPContext.Current.Web.ID))
            {
                if (ReenableInheritance.Checked)
                {
                    web.AllProperties["WorkspaceTermInfoInherit"] = true.ToString();
                    web.Update();
                    web.InheritWorkspaceTermInfoRecursively(UpdateListItems.Checked);
                    return;
                }

                var workspaceTermInfoList = new WorkspaceTermInfoList(web.AllProperties["WorkspaceTermInfo"].ToString());
                if (!workspaceTermInfoList.IsValid)
                {
                    return;
                }

                var nextWorkspaceTermInfoList = new WorkspaceTermInfoList();

                foreach (var workspaceTermInfo in workspaceTermInfoList)
                {
                    if (!workspaceTermInfo.IsValid)
                    {
                        continue;
                    }

                    var taxonomyWebTaggingControl = TaxonomyPanel.FindControl("TWTC" + workspaceTermInfo.TaxFieldStaticName) as TaxonomyWebTaggingControl;

                    if (taxonomyWebTaggingControl == null)
                    {
                        continue; // This should not happen 
                    }

                    // The following setup allows for fields to be left empty without "reducing" the 
                    // WorkspaceTermInfoList
                    TaxonomyFieldValueCollection values = new TaxonomyFieldValueCollection(string.Empty);
                    if (taxonomyWebTaggingControl.Text.Length != 0)
                    {
                        values.PopulateFromLabelGuidPairs(taxonomyWebTaggingControl.Text);
                    }

                    // Now add the termIds to the workspaceTermInfo after it has been reset
                    workspaceTermInfo.TermIds.Clear();
                    foreach (var value in values) // TODO Use to WorkspaceTermInfo.ToString().IndexOf < 0
                    {
                        workspaceTermInfo.TermIds.Add(value.TermGuid.ToString());
                    }

                    if (workspaceTermInfo.IsValid)
                    {
                        nextWorkspaceTermInfoList.Add(workspaceTermInfo);
                    }
                }

                // Update the web with the updated property
                web.AllProperties["WorkspaceTermInfo"] = nextWorkspaceTermInfoList.ToString();
                // Since we've deviated from the parent we break inheritance
                web.AllProperties["WorkspaceTermInfoInherit"] = false.ToString();
                web.Update();

                // Now update all webs below the current web (the current web is ignored
                // by the InheritWorkspaceTermInfoRecursively method as it has WorkspaceTermInfoInherit
                // set to false. Hence it is important to update the current web explicitly.
                web.InheritWorkspaceTermInfoRecursively(UpdateListItems.Checked);

                // And the current web (see explanation above)
                // web.UpdateCurrentWeb(nextWorkspaceTermInfoList, UpdateListItems.Checked);
            }
        }
    }
}
